﻿using GodSharp.Communications.Abstractions;
using System;
using System.Collections.Generic;

namespace GodSharp.Communications
{
    /// <summary>
    /// 
    /// </summary>
    public class ModuleContainer : IModuleContainer
    {
        Dictionary<Type, object> modules = null;

        object _lock = new object();

        /// <summary>
        /// Initializes a new instance of the <see cref="ModuleContainer"/> class.
        /// </summary>
        public ModuleContainer()
        {
            modules = new Dictionary<Type, object>();
        }

        /// <summary>
        /// Adds the module.
        /// </summary>
        /// <param name="type">The type.</param>
        public void AddModule(Type type)
        {
            lock (_lock)
            {
                if (!modules.ContainsKey(type))
                {
                    object obj = Activator.CreateInstance(type);

                    modules.Add(type, obj);
                }
            }
        }

        /// <summary>
        /// Adds the module.
        /// </summary>
        /// <param name="types">The types.</param>
        public void AddModule(ICollection<Type> types)
        {
            if (types == null || types.Count == 0) throw new ArgumentNullException(nameof(types));

            lock (_lock)
            {
                foreach (var type in types)
                {
                    if (!modules.ContainsKey(type))
                    {
                        object obj = Activator.CreateInstance(type);

                        modules.Add(type, obj);
                    }
                }
            }
        }

        /// <summary>
        /// Gets the module.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public object GetModule(Type type)
        {
            lock (_lock)
            {
                if (modules.ContainsKey(type)) return modules[type];
            }

            return null;
        }

        /// <summary>
        /// Gets the module.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public T GetModule<T>(Type type)
        {
            return (T)GetModule(type);
        }
    }
}
